Gerhard Olsson starts adding lap support to Garmin protocol layer.
authorrobertl <robertl>
Fri, 6 Jul 2007 03:35:37 +0000 (03:35 +0000)
committerrobertl <robertl>
Fri, 6 Jul 2007 03:35:37 +0000 (03:35 +0000)
garmin.c
jeeps/gps.h
jeeps/gpsapp.c
jeeps/gpsapp.h
jeeps/gpscom.c
jeeps/gpscom.h
jeeps/gpsmem.c
jeeps/gpsmem.h
jeeps/gpsprot.c
jeeps/gpsprot.h

index 9ee42c813134ba7595988ad36e9266f2c4d21e99..ad4ecd8082fa25833fa856c425d9fa96e04e92e0 100644 (file)
--- a/garmin.c
+++ b/garmin.c
@@ -421,6 +421,94 @@ route_read(void)
 
 }
 
+static
+void
+lap_read_as_track(void)
+{
+       int32 ntracks;
+       GPS_PLap *array;
+       route_head *trk_head = NULL;
+       int trk_num = 0;
+       int index;
+       int i;
+
+       ntracks = GPS_Command_Get_Lap(portname, &array, waypt_read_cb);
+       if ( ntracks <= 0 )
+               return;
+       for (i = 0; i < ntracks; i++) {
+               waypoint *wpt;
+               if (array[i]->index == -1){
+                       index=i;
+               } else {
+                       index=array[i]->index;
+                       index=i;
+               }
+               
+               if ((trk_head == NULL) || (i == 0) ||
+                       /* D906 - last track:index is the track index */
+                       (array[i]->index == -1 && array[i]->track_index != 255) ||
+                       /* D10xx - no real separator, use begin/end time to guess */
+                       (abs(array[i-1]->start_time + array[i]->total_time/100-array[i]->start_time) > 2)
+                       ) {
+                       static struct tm * stmp;
+                       stmp = gmtime(&array[i]->start_time);
+                       trk_head = route_head_alloc();
+                       /*For D906, we would like to use the track_index in the last packet instead...*/
+                       trk_head->rte_num = ++trk_num;
+                       trk_head->rte_name = xmalloc(32);
+                       strftime(trk_head->rte_name, 32, "%Y-%m-%dT%H:%M:%SZ", stmp);
+                       track_add_head(trk_head);
+
+                       wpt = waypt_new();
+
+                       wpt->longitude = array[i]->begin_lon;
+                       wpt->latitude = array[i]->begin_lat;
+                       wpt->heartrate = array[i]->avg_heart_rate;
+                       wpt->cadence = array[i]->avg_cadence;
+                       wpt->speed = array[i]->max_speed;
+                       wpt->creation_time = array[i]->start_time;
+                       wpt->microseconds = 0;
+
+                       wpt->shortname = xmalloc(8);
+                       sprintf(wpt->shortname, "#%d-0", index);
+                       wpt->description = xmalloc(128);
+                       sprintf(wpt->description, "D:%f Cal:%d MS:%f AH:%d MH:%d AC:%d I:%d T:%d",
+                         array[i]->total_distance, array[i]->calories, array[i]->max_speed, array[i]->avg_heart_rate,
+                         array[i]->max_heart_rate, array[i]->avg_cadence, array[i]->intensity, array[i]->trigger_method);
+
+                       track_add_wpt(trk_head, wpt);
+               }
+/*Allow even if no correct location, no skip if invalid */
+/*             if (array[i]->no_latlon) {
+*                      continue;
+*              }
+*/
+               wpt = waypt_new();
+
+               wpt->longitude = array[i]->end_lon;
+               wpt->latitude = array[i]->end_lat;
+               wpt->heartrate = array[i]->avg_heart_rate;
+               wpt->cadence = array[i]->avg_cadence;
+               wpt->speed = array[i]->max_speed;
+               wpt->creation_time = array[i]->start_time + array[i]->total_time/100;
+               wpt->microseconds = 10000*(array[i]->total_time % 100);
+               /*Add fields with no mapping in the description */
+               wpt->shortname = xmalloc(8);
+               sprintf(wpt->shortname, "#%d", index);
+               wpt->description = xmalloc(128);
+               sprintf(wpt->description, "D:%f Cal:%d MS:%f AH:%d MH:%d AC:%d I:%d T:%d (%f,%f)",
+                 array[i]->total_distance, array[i]->calories, array[i]->max_speed, array[i]->avg_heart_rate,
+                 array[i]->max_heart_rate, array[i]->avg_cadence, array[i]->intensity, array[i]->trigger_method, 
+                 array[i]->begin_lon, array[i]->begin_lat);
+
+         track_add_wpt(trk_head, wpt);
+       }
+       while(ntracks) {
+               GPS_Lap_Del(&array[--ntracks]);
+       }
+       xfree(array);
+}
+
 /*
  * Rather than propogate Garmin-specific data types outside of the Garmin
  * code, we convert the PVT (position/velocity/time) data from the receiver
index e307b3aba0360b59bdc3af4d04e2a751a5c7f0de..42018a6a27cb63878f98f553ca6f6a73aecfb344 100644 (file)
@@ -96,6 +96,7 @@ typedef struct GPS_STrack
     unsigned int   no_latlon:1;        /* True if no valid lat/lon found. */
     int32    dspl;             /* Display on map? */
     int32    colour;           /* Colour */
+    float    distance; /* distance traveled in meters.*/
     char     trk_ident[256];   /* Track identifier */
 }
 GPS_OTrack, *GPS_PTrack;
@@ -166,9 +167,10 @@ typedef struct GPS_SWay
 } GPS_OWay, *GPS_PWay;
 
 /*
- * Forerunner Lap data.
+ * Forerunner/Edge Lap data.
  */
-typedef struct GPS_SLap_Data {
+typedef struct GPS_SLap {
+       uint32 index; /* unique index in device or -1 */
        time_t  start_time;
        uint32  total_time;     /* Hundredths of a second */
        float   total_distance; /* In meters */
@@ -177,8 +179,19 @@ typedef struct GPS_SLap_Data {
        double  end_lat;
        double  end_lon;
        int16   calories;
-       UC      track_index;
-} GPS_OLap_Data, *GPS_PLap_Data;
+       uint32 track_index; /* ref to track or -1 */
+       float max_speed; /* In meters per second */
+       unsigned char avg_heart_rate; /* In beats-per-minute, 0 if invalid */
+       unsigned char max_heart_rate; /* In beats-per-minute, 0 if invalid */
+       unsigned char intensity; /* Same as D1001 */
+       unsigned char avg_cadence; /* In revolutions-per-minute, 0xFF if invalid */
+       unsigned char trigger_method; 
+       /*Some D1015 unknown */
+       /*    unsigned char unk1015_1;
+       int16 unk1015_2;
+       int16 unk1015_3;
+       */
+} GPS_OLap, *GPS_PLap;
 
 typedef int (*pcb_fn) (int, struct GPS_SWay **);
 
index 3190681fd418265bcaa3222b6372913b0d5047fe..b0474ab2a2ceb150424aee8392d82302e1cce78b 100644 (file)
@@ -98,10 +98,6 @@ static void   GPS_D400_Send(UC *data, GPS_PWay way, int32 *len);
 static void   GPS_D403_Send(UC *data, GPS_PWay way, int32 *len);
 static void   GPS_D450_Send(UC *data, GPS_PWay way, int32 *len);
 
-static int32    GPS_D500_Get(GPS_PAlmanac *alm, int32 entries, gpsdevh *fd);
-static int32    GPS_D501_Get(GPS_PAlmanac *alm, int32 entries, gpsdevh *fd);
-static int32    GPS_D550_Get(GPS_PAlmanac *alm, int32 entries, gpsdevh *fd);
-static int32    GPS_D551_Get(GPS_PAlmanac *alm, int32 entries, gpsdevh *fd);
 static void   GPS_D500_Send(UC *data, GPS_PAlmanac alm);
 static void   GPS_D501_Send(UC *data, GPS_PAlmanac alm);
 static void   GPS_D550_Send(UC *data, GPS_PAlmanac alm);
@@ -235,13 +231,18 @@ static int32 GPS_A000(const char *port)
 #endif
     gps_pvt_transfer       = -1;
     gps_pvt_type           = -1;
-    gps_prx_waypt_transfer = -1;
-    gps_prx_waypt_type     = -1;
     gps_trk_transfer       = -1;
     gps_trk_type           = -1;
     gps_trk_hdr_type       = -1;
     gps_rte_link_type      = -1;
     
+    gps_prx_waypt_transfer = -1;
+    gps_prx_waypt_type     = -1;
+    gps_almanac_transfer   = -1;
+    gps_almanac_type       = -1;
+    gps_lap_transfer       = -1;
+    gps_lap_type           = -1;
+   
     if(!GPS_Device_Wait(fd))
     {
        GPS_Warning("A001 protocol not supported");
@@ -353,6 +354,8 @@ static void GPS_A001(GPS_PPacket packet)
     gps_prx_waypt_type     = -1;
     gps_almanac_transfer   = -1;
     gps_almanac_type       = -1;
+    gps_lap_transfer       = -1;
+    gps_lap_type           = -1;
     
     entries = packet->n / 3;
     p = packet->data;
@@ -411,15 +414,36 @@ static void GPS_A001(GPS_PPacket packet)
                case 600:
                    gps_date_time_transfer = pA600;
                    break;
+               case 650:
+                   /*  FlightBook Transfer Protocol */
+                   break;
                case 700:
                    gps_position_transfer = pA700;
                    break;
                case 800:
                    gps_pvt_transfer = pA800;
                    break;
+               case 906:
+                   gps_lap_transfer = pA906;
+                   break;
                case 1000:
                    gps_run_transfer = pA1000;
                    break;
+               case 1002:
+                   gps_workout_transfer = pA1002;
+                   break;
+               case 1004:
+                   gps_user_profile_transfer = pA1004;
+                   break;
+               case 1005:
+                   gps_workout_limits_transfer = pA1005;
+                   break;
+               case 1006:
+                   gps_course_transfer = pA1006;
+                   break;
+               case 1009:
+                   gps_course_limits_transfer = pA1009;
+                   break;
            }
            break;
 
@@ -532,27 +556,14 @@ static void GPS_A001(GPS_PPacket packet)
                    continue;
            }
 
-
            else if(lasta<500)
            {
-               if(data<=110 && data>=100)
-               {
-                   gps_prx_waypt_type = data;
-                   continue;
-               }
-               if(data<153 && data>=150)
-               {
-                   gps_prx_waypt_type = data;
-                   continue;
-               }
-               if(data<156 && data>=154)
-               {
-                   gps_prx_waypt_type = data;
-                   continue;
-               }
-               if(data<451)
-               {
-                   if(data==400)
+                   if((data<=110 && data>=100) ||
+                               (data<153 && data>=150) ||
+                               (data<156 && data>=154)) {
+                       gps_prx_waypt_type = data;
+                   }
+                       else if(data==400)
                        gps_prx_waypt_type = pD400;
                    else if(data==403)
                        gps_prx_waypt_type = pD403;
@@ -562,7 +573,6 @@ static void GPS_A001(GPS_PPacket packet)
                        GPS_Protocol_Error(tag,data);
                    continue;
                }
-           }
 
            else if(lasta<600)
            {
@@ -579,7 +589,7 @@ static void GPS_A001(GPS_PPacket packet)
                continue;
            }
 
-           else if(lasta<700)
+           else if(lasta<650)
            {
                if (data == 600) {
                    gps_date_time_type = pD600;
@@ -590,6 +600,13 @@ static void GPS_A001(GPS_PPacket packet)
                }
                continue;
            }
+               
+           else if(lasta<651)
+           {
+                       /*  FlightBook Transfer Protocol, not handled */
+                       continue;
+           }
+               
            else if(lasta<800)
            {
                if(data!=700)
@@ -598,6 +615,7 @@ static void GPS_A001(GPS_PPacket packet)
                    gps_position_type = pD700;
                continue;
            }
+               
            else if(lasta<900)
            {
                if (data == 800)
@@ -609,10 +627,87 @@ static void GPS_A001(GPS_PPacket packet)
                 */
                continue;
            }
+               
            else if (lasta < 1000)
            {
                if (data == 906)
                    gps_lap_type = pD906;
+                       else if (data == 1001)
+                               gps_lap_type = pD1001;
+                       else if (data == 1011)
+                               gps_lap_type = pD1011;
+                       else if (data == 1015)
+                               gps_lap_type = pD1015;
+                       continue;
+           }
+               
+           else if (lasta < 1002)
+           {
+               if (data == 1000)
+                       gps_run_type = pD1000;
+               else if (data == 1009)
+                       gps_run_type = pD1009;
+               else if (data == 1010)
+                       gps_run_type = pD1010;
+               continue;
+           }
+               
+           else if (lasta < 1003)
+           {
+               if (data == 1002)
+                       gps_workout_type = pD1002;
+               else if (data == 1008)
+                       gps_workout_type = pD1008;
+               continue;
+           }
+               
+           else if (lasta < 1004)
+           {
+               if (data == 1003)
+                   gps_workout_occurrence_type = pD1003;
+               continue;
+           }
+               
+           else if (lasta < 1005)
+           {
+               if (data == 1004)
+                   gps_user_profile_type = pD1004;
+               continue;
+           }
+               
+           else if (lasta < 1006)
+           {
+               if (data == 1005)
+                   gps_workout_limits_type = pD1005;
+               continue;
+           }
+               
+           else if (lasta < 1007)
+           {
+               if (data == 1006)
+                   gps_course_type = pD1006;
+               continue;
+           }
+               
+           else if (lasta < 1008)
+           {
+               if (data == 1007)
+                   gps_course_lap_type = pD1007;
+               continue;
+           }
+               
+           else if (lasta < 1009)
+           {
+               if (data == 1012)
+                   gps_course_point_type = pD1012;
+               continue;
+           }
+               
+           else if (lasta < 1010)
+           {
+               if (data == 1013)
+                   gps_course_limits_type = pD1013;
+               continue;
            }
        }
     }
@@ -4006,7 +4101,7 @@ void GPS_D302b_Get(GPS_PTrack *trk, UC *data)
 
 /* @func GPS_D303b_Get ******************************************************
 **
-** Get track data (A302 protocol) -- XXX used in Forerunner 301
+** Get track data (A302 protocol) -- used in Forerunner 301
 **
 ** @param [w] trk [GPS_PTrack *] track
 ** @param [r] data [UC *] packet data
@@ -4073,7 +4168,8 @@ void GPS_D303b_Get(GPS_PTrack *trk, UC *data)
      */
     switch (gps_trk_type) {
     case pD304:
-       p+=4; /* A float indicating number of meters travelled. */
+       (*trk)->distance = GPS_Util_Get_Float(p);
+       p+=sizeof(float); /* A float indicating number of meters travelled. */
        
        (*trk)->heartrate = (*p++);
        /* crank cadence, RPM, 0xff if invalid.  */
@@ -4866,34 +4962,33 @@ int32 GPS_A500_Get(const char *port, GPS_PAlmanac **alm)
 {
     static UC data[2];
     gpsdevh *fd;
-    GPS_PPacket tra;
-    GPS_PPacket rec;
-    int32 n;
-    int32 i;
-    int32 ret;
+    GPS_PPacket trapkt;
+    GPS_PPacket recpkt;
+    int32 i, n;
+
+    if (gps_almanac_transfer == -1)
+       return GPS_UNSUPPORTED;
     
     if(!GPS_Device_On(port, &fd))
        return gps_errno;
 
-    if(!(tra = GPS_Packet_New()) || !(rec = GPS_Packet_New()))
+    if (!(trapkt = GPS_Packet_New() ) || !(recpkt = GPS_Packet_New()))
        return MEMORY_ERROR;
 
-
     GPS_Util_Put_Short(data,
                       COMMAND_ID[gps_device_command].Cmnd_Transfer_Alm);
-    GPS_Make_Packet(&tra, LINK_ID[gps_link_type].Pid_Command_Data,
+    GPS_Make_Packet(&trapkt, LINK_ID[gps_link_type].Pid_Command_Data,
                    data,2);
-    if(!GPS_Write_Packet(fd,tra))
+    if(!GPS_Write_Packet(fd,trapkt))
        return gps_errno;
-    if(!GPS_Get_Ack(fd, &tra, &rec))
+    if(!GPS_Get_Ack(fd, &trapkt, &recpkt))
        return gps_errno;
-
-    if(!GPS_Packet_Read(fd, &rec))
+    if(!GPS_Packet_Read(fd, &recpkt))
        return gps_errno;
-    if(!GPS_Send_Ack(fd, &tra, &rec))
+    if(!GPS_Send_Ack(fd, &trapkt, &recpkt))
        return gps_errno;
 
-    n = GPS_Util_Get_Short(rec->data);
+    n = GPS_Util_Get_Short(recpkt->data);
 
     if(n)
        if(!((*alm)=(GPS_PAlmanac *)malloc(n*sizeof(GPS_PAlmanac))))
@@ -4901,51 +4996,67 @@ int32 GPS_A500_Get(const char *port, GPS_PAlmanac **alm)
            GPS_Error("A500_Get: Insufficient memory");
            return MEMORY_ERROR;
        }
-    for(i=0;i<n;++i)
+
+    for(i=0;i<n;++i) {
        if(!((*alm)[i]=GPS_Almanac_New()))
            return MEMORY_ERROR;
+               if(!GPS_Packet_Read(fd, &recpkt)) {
+                       return gps_errno;
+               }
     
+               if(!GPS_Send_Ack(fd, &trapkt, &recpkt)) {
+                       return gps_errno;
+               }
 
-    switch(gps_almanac_type)
-    {
+               switch(gps_almanac_type) {
     case pD500:
-       ret = GPS_D500_Get(*alm,n,fd);
+       GPS_A500_Translate(recpkt->data, &((*alm)[i]));
        break;
     case pD501:
-       ret = GPS_D501_Get(*alm,n,fd);
+       GPS_A500_Translate(recpkt->data, &((*alm)[i]));
+       (*alm)[i]->hlth=recpkt->data[42];
        break;
     case pD550:
-       ret = GPS_D550_Get(*alm,n,fd);
+       (*alm)[i]->svid = recpkt->data[0];
+       GPS_A500_Translate(recpkt->data+1, &((*alm)[i]));
        break;
     case pD551:
-       ret = GPS_D551_Get(*alm,n,fd);
+       (*alm)[i]->svid = recpkt->data[0];
+       GPS_A500_Translate(recpkt->data+1, &((*alm)[i]));
+       (*alm)[i]->hlth = recpkt->data[43];
        break;
     default:
        GPS_Error("A500_GET: Unknown almanac protocol");
        return PROTOCOL_ERROR;
     }
+               /* Cheat and don't _really_ pass the trkpt back */
+/*             cb(n, NULL);*/
+       }
 
-    if(ret < 0) return ret;
-    if(ret != n)
-    {
-       GPS_Error("A500_GET: Almanac entry number mismatch");
+    if(!GPS_Packet_Read(fd, &recpkt))
+       return gps_errno;
+    if(!GPS_Send_Ack(fd, &trapkt, &recpkt))
+       return gps_errno;
+    if(recpkt->type != LINK_ID[gps_link_type].Pid_Xfer_Cmplt) {
+       GPS_Error("A500_Get: Error transferring almanac");
        return FRAMING_ERROR;
     }
     
+    if(i != n) {
+       GPS_Error("A500_GET: Almanac entry number mismatch");
+       return FRAMING_ERROR;
+    }
     
-    GPS_Packet_Del(&tra);
-    GPS_Packet_Del(&rec);
+    GPS_Packet_Del(&trapkt);
+    GPS_Packet_Del(&recpkt);
 
     if(!GPS_Device_Off(fd))
        return gps_errno;
 
-    return ret;
+    return n;
 }
 
 
-
-
-
 /* @func GPS_A500_Send **************************************************
 **
 ** Send almanac to GPS
@@ -5125,216 +5236,6 @@ int32 GPS_A500_Send(const char *port, GPS_PAlmanac *alm, int32 n)
     return 1;
 }
 
-
-
-/* @funcstatic GPS_D500_Get ********************************************
-**
-** Get almanac data
-**
-** @param [w] alm [GPS_PAlmanac *] almanac array
-** @param [r] entries [int32] number of packets to receive
-** @param [r] fd [int32] file descriptor
-**
-** @return [int32] number of entries read
-************************************************************************/
-static int32 GPS_D500_Get(GPS_PAlmanac *alm, int32 entries, gpsdevh *fd)
-{
-    GPS_PPacket tra;
-    GPS_PPacket rec;
-    int32 i;
-    
-    if(!(tra = GPS_Packet_New()) || !(rec = GPS_Packet_New()))
-       return MEMORY_ERROR;
-
-
-    for(i=0;i<entries;++i)
-    {
-       if(!GPS_Packet_Read(fd, &rec))
-           return gps_errno;
-       
-       if(!GPS_Send_Ack(fd, &tra, &rec))
-           return gps_errno;
-
-       GPS_A500_Translate(rec->data, &alm[i]);
-    }
-    
-
-    if(!GPS_Packet_Read(fd, &rec))
-       return gps_errno;
-    
-    if(!GPS_Send_Ack(fd, &tra, &rec))
-       return gps_errno;
-    
-
-    if(rec->type != LINK_ID[gps_link_type].Pid_Xfer_Cmplt)
-    {
-       GPS_Error("D500_GET: Error transferring almanac");
-       return FRAMING_ERROR;
-    }
-
-    GPS_Packet_Del(&tra);
-    GPS_Packet_Del(&rec);
-       
-    return i;
-}
-
-
-/* @funcstatic  GPS_D501_Get ********************************************
-**
-** Get almanac data
-**
-** @param [w] alm [GPS_PAlmanac *] almanac array
-** @param [r] entries [int32] number of packets to receive
-** @param [r] fd [int32] file descriptor
-**
-** @return [int32] number of entries read
-************************************************************************/
-static int32 GPS_D501_Get(GPS_PAlmanac *alm, int32 entries, gpsdevh *fd)
-{
-    GPS_PPacket tra;
-    GPS_PPacket rec;
-    int32 i;
-
-    if(!(tra = GPS_Packet_New()) || !(rec = GPS_Packet_New()))
-       return MEMORY_ERROR;
-
-
-    for(i=0;i<entries;++i)
-    {
-       if(!GPS_Packet_Read(fd, &rec))
-           return gps_errno;
-       if(!GPS_Send_Ack(fd, &tra, &rec))
-           return gps_errno;
-
-       GPS_A500_Translate(rec->data, &alm[i]);
-       alm[i]->hlth=rec->data[42];
-    }
-    
-
-    if(!GPS_Packet_Read(fd, &rec))
-       return gps_errno;
-    if(!GPS_Send_Ack(fd, &tra, &rec))
-       return gps_errno;
-    
-
-    if(rec->type != LINK_ID[gps_link_type].Pid_Xfer_Cmplt)
-    {
-       GPS_Error("D501_GET: Error transferring almanac");
-       return FRAMING_ERROR;
-    }
-    
-    GPS_Packet_Del(&tra);
-    GPS_Packet_Del(&rec);
-       
-    return i;
-}
-
-
-
-/* @funcstatic GPS_D550_Get *********************************************
-**
-** Get almanac data
-**
-** @param [w] alm [GPS_PAlmanac *] almanac array
-** @param [r] entries [int32] number of packets to receive
-** @param [r] fd [int32] file descriptor
-**
-** @return [int32] number of entries read
-************************************************************************/
-static int32 GPS_D550_Get(GPS_PAlmanac *alm, int32 entries, gpsdevh *fd)
-{
-    GPS_PPacket tra;
-    GPS_PPacket rec;
-    int32 i;
-    
-    if(!(tra = GPS_Packet_New()) || !(rec = GPS_Packet_New()))
-       return MEMORY_ERROR;
-
-
-    for(i=0;i<entries;++i)
-    {
-       if(!GPS_Packet_Read(fd, &rec))
-           return gps_errno;
-       if(!GPS_Send_Ack(fd, &tra, &rec))
-           return gps_errno;
-
-       alm[i]->svid = rec->data[0];
-       GPS_A500_Translate(rec->data+1, &alm[i]);
-    }
-    
-
-    if(!GPS_Packet_Read(fd, &rec))
-       return gps_errno;
-    if(!GPS_Send_Ack(fd, &tra, &rec))
-       return gps_errno;
-    
-    if(rec->type != LINK_ID[gps_link_type].Pid_Xfer_Cmplt)
-    {
-       GPS_Error("D550_GET: Error transferring almanac");
-       return FRAMING_ERROR;
-    }
-
-    GPS_Packet_Del(&tra);
-    GPS_Packet_Del(&rec);
-       
-    return i;
-}
-
-
-
-/* @funcstatic GPS_D551_Get *********************************************
-**
-** Get almanac data
-**
-** @param [w] alm [GPS_PAlmanac *] almanac array
-** @param [r] entries [int32] number of packets to receive
-** @param [r] fd [int32] file descriptor
-**
-** @return [int32] number of entries read
-************************************************************************/
-static int32 GPS_D551_Get(GPS_PAlmanac *alm, int32 entries, gpsdevh *fd)
-{
-    GPS_PPacket tra;
-    GPS_PPacket rec;
-    int32 i;
-    
-    if(!(tra = GPS_Packet_New()) || !(rec = GPS_Packet_New()))
-       return MEMORY_ERROR;
-
-
-    for(i=0;i<entries;++i)
-    {
-       if(!GPS_Packet_Read(fd, &rec))
-           return gps_errno;
-       if(!GPS_Send_Ack(fd, &tra, &rec))
-           return gps_errno;
-
-       alm[i]->svid = rec->data[0];
-       GPS_A500_Translate(rec->data+1, &alm[i]);
-       alm[i]->hlth = rec->data[43];
-    }
-    
-
-    if(!GPS_Packet_Read(fd, &rec))
-       return gps_errno;
-    if(!GPS_Send_Ack(fd, &tra, &rec))
-       return gps_errno;
-    
-
-    if(rec->type != LINK_ID[gps_link_type].Pid_Xfer_Cmplt)
-    {
-       GPS_Error("D551_GET: Error transferring almanac\n");
-       return FRAMING_ERROR;
-    }
-
-    GPS_Packet_Del(&tra);
-    GPS_Packet_Del(&rec);
-       
-    return i;
-}
-
-
-
 /* @funcstatic  GPS_A500_Translate ***************************************
 **
 ** Translate almanac packet to almanac structure
@@ -6104,23 +6005,22 @@ void GPS_D800_Get(GPS_PPacket packet, GPS_PPvt_Data *pvt)
     
     return;
 }
-#if XXX /*   FIXME/PLACEHOLDER */
 
 /* @func GPS_A906_Get ******************************************************
 **
 ** Get lap data from GPS
 **
 ** @param [r] port [const char *] serial port
-** @param [w] trk [GPS_PLap_Data **] lap array
+** @param [w] trk [GPS_PLap **] lap array
 **
 ** @return [int32] number of lap entries
 ************************************************************************/
 
-int32 GPS_A906_Get(const char *port, GPS_OLap_Data **lap)
+int32 GPS_A906_Get(const char *port, GPS_PLap **lap, pcb_fn cb)
 {
     static UC data[2];
     gpsdevh *fd;
-    GPS_PPacket lappkt;
+    GPS_PPacket trapkt;
     GPS_PPacket recpkt;
     int32 i, n;
 
@@ -6130,20 +6030,20 @@ int32 GPS_A906_Get(const char *port, GPS_OLap_Data **lap)
     if (!GPS_Device_On(port, &fd))
        return gps_errno;
 
-    if (!(lappkt = GPS_Packet_New() ) || !(recpkt = GPS_Packet_New()))
+    if (!(trapkt = GPS_Packet_New() ) || !(recpkt = GPS_Packet_New()))
        return MEMORY_ERROR;
 
     GPS_Util_Put_Short(data,
                        COMMAND_ID[gps_device_command].Cmnd_Transfer_Lap);
-    GPS_Make_Packet(&lappkt, LINK_ID[gps_link_type].Pid_Command_Data,
+    GPS_Make_Packet(&trapkt, LINK_ID[gps_link_type].Pid_Command_Data,
                     data,2);
-    if(!GPS_Write_Packet(fd,lappkt))
+    if(!GPS_Write_Packet(fd,trapkt))
         return gps_errno;
-    if(!GPS_Get_Ack(fd, &lappkt, &recpkt))
+    if(!GPS_Get_Ack(fd, &trapkt, &recpkt))
         return gps_errno;
     if(!GPS_Packet_Read(fd, &recpkt))
         return gps_errno;
-    if(!GPS_Send_Ack(fd, &lappkt, &recpkt))
+    if(!GPS_Send_Ack(fd, &trapkt, &recpkt))
         return gps_errno;
 
     n = GPS_Util_Get_Short(recpkt->data);
@@ -6155,48 +6055,86 @@ int32 GPS_A906_Get(const char *port, GPS_OLap_Data **lap)
             return MEMORY_ERROR;
         }
 
-    for(i=0;i<n;++i)
-        if(!((*trk)[i]=GPS_Track_New()))
+    for(i=0;i<n;++i) {
+        if(!((*lap)[i]=GPS_Lap_New()))
             return MEMORY_ERROR;
+       if(!GPS_Packet_Read(fd, &recpkt)) {
+               return gps_errno;
+       }
 
-    switch(gps_lap_type) {
-       case pD906:
-           ret = GPS_D906_Get(*lap, n, fd);
-           if (ret < 0) return ret;
-           break;
-       default:
-           GPS_Error("A906_Get: Unknown Lap protocol %d\n", gps_lap_type);
-           return PROTOCOL_ERROR;
+       if(!GPS_Send_Ack(fd, &trapkt, &recpkt)) {
+               return gps_errno;
+       }
+
+       switch(gps_lap_type) {
+           case pD906:
+                   case pD1001:
+                   case pD1011:
+                   case pD1015:
+                           GPS_D1011b_Get(&((*lap)[i]),recpkt->data);
+               break;
+           default:
+               GPS_Error("A906_Get: Unknown Lap protocol %d\n", gps_lap_type);
+               return PROTOCOL_ERROR;
+       }
+
+       /* Cheat and don't _really_ pass the trkpt back */
+       cb(n, NULL);
     }
-    if (ret != n) {
-       GPS_Error("A906_Get: got %d lap entries.  Expected %d\n", ret, n);
+
+    if(!GPS_Packet_Read(fd, &recpkt))
+       return gps_errno;
+    if(!GPS_Send_Ack(fd, &trapkt, &recpkt))
+       return gps_errno;
+    if(recpkt->type != LINK_ID[gps_link_type].Pid_Xfer_Cmplt) {
+       GPS_Error("A906_Get: Error transferring laps");
        return FRAMING_ERROR;
     }
-    GPS_Packet_Del(&lap);
-    GPS_Packet_Del(&rec);
+
+    if(i != n) {
+       GPS_Error("A906_GET: Lap entry number mismatch");
+       return FRAMING_ERROR;
+    }
+    
+    GPS_Packet_Del(&trapkt);
+    GPS_Packet_Del(&recpkt);
 
     if (!GPS_Device_Off(fd))
        return gps_errno;
-
-    return ret;
+    return n;
 }
-#endif /* FIXME */
 
-/* @func GPS_D906_Get ******************************************************
+/* @func GPS_D1011b_Get ******************************************************
 **
-** Convert packet to lap structure
+** Convert packet D906, D1001, D1011, D1015 to lap structure
 **
 ** @param [r] packet [GPS_PPacket] packet
-** @param [w] pvt [GPS_PLap_Data *] lap structure
+** @param [w] pvt [GPS_PLap *] lap structure
 **
 ** @return [void]
 ************************************************************************/
-void GPS_D906_Get(GPS_PPacket packet, GPS_PLap_Data *Lap)
+void GPS_D1011b_Get(GPS_PLap *Lap, UC *p)
 {
-    UC *p;
     uint32 t;
     
-    p = packet->data;
+       /* Lap index (not in D906) */
+       switch(gps_lap_type) {
+               case pD906:
+                       (*Lap)->index = -1;
+                       break;
+               case pD1001:
+                       (*Lap)->index = GPS_Util_Get_Uint(p);
+                       p+=sizeof(uint32);
+                       break;
+               case pD1011:
+               case pD1015:
+                       (*Lap)->index = GPS_Util_Get_Short(p);
+                       p+=sizeof(uint16);
+                       p+=sizeof(uint16); /*unused*/
+                       break;
+               default:
+                       break;
+       }
 
     t = GPS_Util_Get_Uint(p);
     (*Lap)->start_time = GPS_Math_Gtime_To_Utime((time_t)t);
@@ -6207,7 +6145,10 @@ void GPS_D906_Get(GPS_PPacket packet, GPS_PLap_Data *Lap)
 
     (*Lap)->total_distance = GPS_Util_Get_Float(p);
     p+=sizeof(float);
-
+       if(gps_lap_type != pD906){
+               (*Lap)->max_speed = GPS_Util_Get_Float(p);
+               p+=sizeof(float);
+       }
 
     (*Lap)->begin_lat = GPS_Math_Semi_To_Deg(GPS_Util_Get_Int(p));
     p+=sizeof(int32);
@@ -6221,16 +6162,53 @@ void GPS_D906_Get(GPS_PPacket packet, GPS_PLap_Data *Lap)
     (*Lap)->calories = GPS_Util_Get_Short(p);
     p+=sizeof(int16);
 
-    (*Lap)->track_index = *p++;
+       /* Track index, only in D906*/
+    if(gps_lap_type == pD906){
+       (*Lap)->track_index = *p++;
+       p++; /*Unused*/
+               
+       /*Last field, no more to do */
+       return;
+    } else {
+       (*Lap)->track_index = -1;
+    }
+
+    (*Lap)->avg_heart_rate = *p++;
+    (*Lap)->max_heart_rate = *p++;
+    (*Lap)->intensity = *p++;
+
+    switch(gps_lap_type) {
+       case pD1001:
+                       /*No more fields */
+           return;
+       case pD1011:
+       case pD1015:
+           (*Lap)->avg_cadence = *p++;
+           (*Lap)->trigger_method = *p++;
+           break;
+       default:
+           /*pD906 already returned*/
+           break;
+    }
+
+    if (gps_lap_type==pD1015) {
+       /*some unknown fields like 04 dc 44 ff ff */
+       /*              (*Lap)->unk1015_1 = *p++; normally 4?
+       (*Lap)->unk1015_2 = GPS_Util_Get_Short(p);wkt related , ffff otherwise
+       p+=sizeof(int16);
+       (*Lap)->unk1015_3 = GPS_Util_Get_Short(p);ffff ?
+       p+=sizeof(int16);
+       */
+    }
 
     return;
 }
 
+
 /* 
  *  It's unfortunate that these aren't constant and therefore switchable,
  *  but they really are runtime variable.  Sigh.
  */
-
 const char *
 Get_Pkt_Type(unsigned char p, unsigned short d0, const char **xinfo)
 {
@@ -6259,10 +6237,25 @@ Get_Pkt_Type(unsigned char p, unsigned short d0, const char **xinfo)
                        case 452: *xinfo = "Xfer Wkt Occurrences"; break;
                        case 453: *xinfo = "Xfer User Profile "; break;
                        case 454: *xinfo = "Xfer Wkt Limits"; break;
+                       case 561: *xinfo = "Xfer Courses"; break;
+                       case 562: *xinfo = "Xfer Course Laps"; break;
+                       case 563: *xinfo = "Xfer Course Point"; break;
+                       case 564: *xinfo = "Xfer Course Tracks"; break;
+                       case 565: *xinfo = "Xfer Course Limits"; break;
+
                        default: *xinfo = "Unknown";
                }
                return "CMDDAT";
        }
+       if (p == LT.Pid_Protocol_Array)
+               return "PRTARR";
+       if (p == LT.Pid_Product_Rqst)
+               return "PRDREQ";
+       if (p == LT.Pid_Product_Data)
+               return "PRDDAT";
+       if (p == LT.Pid_Ext_Product_Data)
+               return "PRDEDA";
+
        if (p == LT.Pid_Xfer_Cmplt)
                return "XFRCMP";
        if (p == LT.Pid_Date_Time_Data)
@@ -6291,19 +6284,44 @@ Get_Pkt_Type(unsigned char p, unsigned short d0, const char **xinfo)
                return "LNKDAT";
        if (p == LT.Pid_Trk_Hdr)
                return "TRKHDR";
-       if (p == LT.Pid_Protocol_Array)
-               return "PRTARR";
-       if (p == LT.Pid_Product_Rqst)
-               return "PRDREQ";
-       if (p == LT.Pid_Product_Data)
-               return "PRDDAT";
+
+       if (p == LT.Pid_FlightBook_Record)
+               return "FLIBOO";
+       if (p == LT.Pid_Lap)
+               return "LAPDAT";
+       if (p == LT.Pid_Wpt_Cat_Data)
+               return "WPTCAT";
+       if (p == LT.Pid_Run)
+               return "RUNDAT";
+       if (p == LT.Pid_Workout)
+               return "WKTDAT";
+       if (p == LT.Pid_Workout_Occurrence)
+               return "WKTOCC";
+       if (p == LT.Pid_Fitness_User_Profile)
+               return "UPROFI";
+       if (p == LT.Pid_Workout_Limits)
+               return "WKTLIM";
+       if (p == LT.Pid_Course)
+               return "CRSDAT";
+       if (p == LT.Pid_Course_Lap)
+               return "CRSLAP";
+       if (p == LT.Pid_Course_Point)
+               return "CRSPOI";
+       if (p == LT.Pid_Course_Trk_Hdr)
+               return "CRSTHD";
+       if (p == LT.Pid_Course_Trk_Data)
+               return "CRSTDA";
+       if (p == LT.Pid_Course_Limits)
+               return "CRSLIM";
+       if (p == LT.Pid_Trk2_Hdr)
+               return "TRKHD2";
+               
        if (p == GUSB_REQUEST_BULK) 
                return "REQBLK";
        if (p == GUSB_SESSION_START)
                return "SESREQ";
        if (p == GUSB_SESSION_ACK)
                return "SESACK";
-       if (p == 152)
-               return "WPTCAT";
+               
        return "UNKNOWN";
 }
index ee64168475ea5949fe44224d80d586eb14a439bd..677b448d98a6f90b6144febd5fc2be8148dda1e0 100644 (file)
@@ -23,13 +23,13 @@ int32  GPS_A201_Send(const char *port, GPS_PWay *way, int32 n);
 int32  GPS_A300_Get(const char *port, GPS_PTrack **trk, pcb_fn cb);
 int32  GPS_A301_Get(const char *port, GPS_PTrack **trk, pcb_fn cb);
 int32  GPS_A300_Send(const char *port, GPS_PTrack *trk, int32 n);
-int32  GPS_A301_Send(const char *port, GPS_PTrack *trk, int32 n);
+int32  GPS_A301_Send(const char *port, GPS_PTrack *trk, int32 n); /*A302*/
 
 int32  GPS_D300_Get(GPS_PTrack *trk, int32 entries, gpsdevh *h);
 void   GPS_D300b_Get(GPS_PTrack *trk, UC *data);
 void   GPS_D301b_Get(GPS_PTrack *trk, UC *data);
 void   GPS_D302b_Get(GPS_PTrack *trk, UC *data);
-void   GPS_D303b_Get(GPS_PTrack *trk, UC *data);
+void   GPS_D303b_Get(GPS_PTrack *trk, UC *data); /*D304*/
 void   GPS_D310_Get(GPS_PTrack *trk, UC *s);
 void   GPS_D311_Get(GPS_PTrack *trk, UC *s);
 void   GPS_D300_Send(UC *data, GPS_PTrack trk);
@@ -58,6 +58,43 @@ int32  GPS_A800_Off(const char *port, gpsdevh **fd);
 int32  GPS_A800_Get(gpsdevh **fd, GPS_PPvt_Data *packet);
 void   GPS_D800_Get(GPS_PPacket packet, GPS_PPvt_Data *pvt);
 
+int32 GPS_A906_Get(const char *port, GPS_PLap **lap, pcb_fn cb);
+void GPS_D1011b_Get(GPS_PLap *Lap,UC *data); /*D906 D1001 D1015*/
+
+/* Unhandled documented protocols, as of:
+  Garmin Device Interface Specification, May 19, 2006, Drawing Number: 001-00063-00 Rev. C
+A650 \96 FlightBook Transfer Protocol
+A1000 \96 Run Transfer Protocol
+       Capability A1000: D1009
+               D1000 D1010
+A1002 \96 Workout Transfer Protocol
+       Capability A1002: D1008
+               D1002
+       Capability A1003: D1003
+A1004 \96 Fitness User Profile Transfer Protocol
+       Capability A1004: D1004
+A1005 \96 Workout Limits Transfer Protocol
+       Capability A1005: D1005
+A1006 \96 Course Transfer Protocol
+       Capability A1006: D1006
+       Capability A1007: D1007
+       Capability A1008: D1012
+A1009 \96 Course Limits Transfer Protocol
+       Capability A1009: D1013
+*/
+/* Unimplemted and Undocumented, as listed from the following device/sw:
+       GF305 3.70
+  
+Capability A601: D601
+Capability A801: D801
+
+Capability A902:
+Capability A903:
+Capability A907: D907 D908 D909 D910
+Capability A918: D918
+Capability A1013: D1014
+*/
+
 const char * Get_Pkt_Type(unsigned char p, unsigned short d0, const char **xinfo);
 
 
index e2fe2afd664999b136a688ba683f7c4a95a31c3d..3063b510afd7db5bbdd0e2e5d084a1d6e3c34f77 100644 (file)
@@ -361,6 +361,9 @@ int32 GPS_Command_Get_Almanac(const char *port, GPS_PAlmanac **alm)
 {
     int32 ret=0;
 
+    if(gps_almanac_transfer == -1)
+       return GPS_UNSUPPORTED;
+
     switch(gps_almanac_transfer)
     {
     case pA500:
@@ -391,6 +394,9 @@ int32 GPS_Command_Send_Almanac(const char *port, GPS_PAlmanac *alm, int32 n)
 {
     int32 ret=0;
 
+       if(gps_almanac_transfer == -1)
+               return GPS_UNSUPPORTED;
+
     switch(gps_almanac_transfer)
     {
     case pA500:
@@ -635,3 +641,50 @@ int32 GPS_Command_Pvt_Get(gpsdevh **fd, GPS_PPvt_Data *pvt)
 
     return ret;
 }    
+
+/* @func GPS_Command_Get_Lap ***************************************
+**
+** Get lap from GPS
+**
+** @param [r] port [const char *] serial port
+** @param [w] way [GPS_PLap **] pointer to lap array
+**
+** @return [int32] number of lap entries
+************************************************************************/
+
+int32 GPS_Command_Get_Lap(const char *port, GPS_PLap **lap, pcb_fn cb)
+{
+    int32 ret=0;
+
+    if(gps_lap_transfer == -1)
+       return GPS_UNSUPPORTED;
+
+    switch(gps_lap_transfer)
+    {
+       case pA906:
+           ret = GPS_A906_Get(port,lap, cb);
+           break;
+       default:
+           GPS_Error("Get_Lap: Unknown lap protocol");
+           return PROTOCOL_ERROR;
+    }
+
+    return ret;
+}    
+ /*Stubs for unimplemented stuff*/
+int32  GPS_Command_Get_Workout(const char *port, void **lap, int (*cb)(int, struct GPS_SWay **)){
+  return 0;
+}  
+int32  GPS_Command_Get_Fitness_User_Profile(const char *port, void **lap, int (*cb)(int, struct GPS_SWay **)){
+  return 0;
+}  
+int32  GPS_Command_Get_Workout_Limits(const char *port, void **lap, int (*cb)(int, struct GPS_SWay **)){
+  return 0;
+}  
+int32  GPS_Command_Get_Course(const char *port, void **lap, int (*cb)(int, struct GPS_SWay **)){
+  return 0;
+}  
+int32  GPS_Command_Get_Course_Limits(const char *port, void **lap, int (*cb)(int, struct GPS_SWay **)){
+  return 0;
+}  
+
index 96e10f0558344ca6081594ff2c2207d8fc6424b9..4c490cd42a617396ccd9a86ecc97be75c3031250 100644 (file)
@@ -37,7 +37,13 @@ int32  GPS_Command_Send_Proximity(const char *port, GPS_PWay *way, int32 n);
 int32  GPS_Command_Get_Route(const char *port, GPS_PWay **way);
 int32  GPS_Command_Send_Route(const char *port, GPS_PWay *way, int32 n);
 
+int32  GPS_Command_Get_Lap(const char *port, GPS_PLap **lap, int (*cb)(int, struct GPS_SWay **));
 
+int32  GPS_Command_Get_Workout(const char *port, void **lap, int (*cb)(int, struct GPS_SWay **));
+int32  GPS_Command_Get_Fitness_User_Profile(const char *port, void **lap, int (*cb)(int, struct GPS_SWay **));
+int32  GPS_Command_Get_Workout_Limits(const char *port, void **lap, int (*cb)(int, struct GPS_SWay **));
+int32  GPS_Command_Get_Course(const char *port, void **lap, int (*cb)(int, struct GPS_SWay **));
+int32  GPS_Command_Get_Course_Limits(const char *port, void **lap, int (*cb)(int, struct GPS_SWay **));
 #endif
 
 #ifdef __cplusplus
index 5bfe84afa6f369e80f6caf535d6aa7d0651db60b..47b3be3297f3fd80503a0e686fd33516b80154a8 100644 (file)
@@ -300,3 +300,42 @@ void GPS_Way_Del(GPS_PWay *thys)
     return;
 }
 
+/* @func GPS_Lap_New ***********************************************
+**
+** Lap constructor
+**
+** @return [GPS_PLap] virgin track
+**********************************************************************/
+
+GPS_PLap GPS_Lap_New(void)
+{
+    GPS_PLap ret;
+    
+    if(!(ret=(GPS_PLap)calloc(1,sizeof(GPS_OLap))))
+    {
+       perror("malloc");
+       fprintf(stderr,"GPS_Lap_New: Insufficient memory");
+       fflush(stderr);
+       return NULL;
+    }
+
+    return ret;
+}
+
+
+
+/* @func GPS_Lap_Del ***********************************************
+**
+** Lap destructor
+**
+** @param [w] thys [GPS_PLap *] track to delete
+**
+** @return [void]
+**********************************************************************/
+
+void GPS_Lap_Del(GPS_PLap *thys)
+{
+    free((void *)*thys);
+
+    return;
+}
index f4e5f505d6bb700cf1df3f6c9534f11813732d34..2f5bbc2cef9159d5247efc10f4b5d7d599822ddf 100644 (file)
@@ -19,6 +19,8 @@ GPS_PTrack    GPS_Track_New(void);
 void          GPS_Track_Del(GPS_PTrack *thys);
 GPS_PWay      GPS_Way_New(void);
 void          GPS_Way_Del(GPS_PWay *thys);
+GPS_PLap         GPS_Lap_New(void);
+void          GPS_Lap_Del(GPS_PLap *thys);
 
 #endif
 
index 63976d995f331471c6dd4398762ffc78e542107d..58e8a11823e2131b056db652738268184de0de49 100644 (file)
@@ -37,7 +37,7 @@ static int32 gps_n_tag_unknown = 0;
 struct COMMANDDATA COMMAND_ID[2]=
 {
     {
-       0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x31,0x32,92,117,121,450
+       0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x31,0x32,92,117,121,450,451,452,453,454,561,562,563,564,564
     }
     ,
     {
@@ -48,17 +48,24 @@ struct COMMANDDATA COMMAND_ID[2]=
 struct LINKDATA LINK_ID[3]=
 {
     {
-       0x06,0,0,0,0,0,0x15,0,0,0,0,0,0,0,0,0,0xfd,0xfe,0xff
+       0xfd,0xfe,0xff,248,
+       0x06,0,0,0,0,0,0x15,0,0,0,0,
+       0,0,0,0,0,
+       0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
     }
     ,
     {
-       0x06,0x0a,0x0c,0x0e,0x11,0x13,0x15,0x1b,0x1d,0x1e,
-       0x1f,0x22,0x23,0x33,0x62,0x63,0xfd,0xfe,0xff
+       0xfd,0xfe,0xff,248,
+       0x06,0x0a,0x0c,0x0e,0x11,0x13,0x15,0x1b,0x1d,0x1e,0x1f,
+       0x22,0x23,0x33,0x62,0x63,
+       134,149,152,990,991,992,993,994,1061,1062,1063,1064,1065,1066,222
     }
     ,
     {
+       0xfd,0xfe,0xff,248,
        0x06,0x0b,0x0c,0x14,0x18,0,0x15,0x23,0x25,0x27,0x04,
-       0,0x2b,0,0,0,0xfd,0xfe,0xff
+       0,0x2b,0,0,0,
+       0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
     }
 };
 
index 05ff718578e8a8bdcb841ea4b960551725ee0c3e..2e30d20c9613ddff7957949296199e4412982c13 100644 (file)
@@ -14,28 +14,44 @@ extern "C"
 
 struct LINKDATA
 {
-    UC Pid_Ack_Byte;
-    UC Pid_Command_Data;
-    UC Pid_Xfer_Cmplt;
-    UC Pid_Date_Time_Data;
-    UC Pid_Position_Data;
-    UC Pid_Prx_Wpt_Data;
-    UC Pid_Nak_Byte;
-    UC Pid_Records;
-    UC Pid_Rte_Hdr;
-    UC Pid_Rte_Wpt_Data;
-    UC Pid_Almanac_Data;
-    UC Pid_Trk_Data;
-    UC Pid_Wpt_Data;
-    UC Pid_Pvt_Data;
-    UC Pid_Rte_Link_Data;
-    UC Pid_Trk_Hdr;
-    UC Pid_Protocol_Array;
-    UC Pid_Product_Rqst;
-    UC Pid_Product_Data;
-    UC Pid_Wpt_Cat_Data;
-}
-;
+    US Pid_Protocol_Array;
+    US Pid_Product_Rqst;
+    US Pid_Product_Data;
+    US Pid_Ext_Product_Data;
+
+    US Pid_Ack_Byte;
+    US Pid_Command_Data;
+    US Pid_Xfer_Cmplt;
+    US Pid_Date_Time_Data;
+    US Pid_Position_Data;
+    US Pid_Prx_Wpt_Data;
+    US Pid_Nak_Byte;
+    US Pid_Records;
+    US Pid_Rte_Hdr;
+    US Pid_Rte_Wpt_Data;
+    US Pid_Almanac_Data;
+    US Pid_Trk_Data;
+    US Pid_Wpt_Data;
+    US Pid_Pvt_Data;
+    US Pid_Rte_Link_Data;
+    US Pid_Trk_Hdr;
+       
+    US Pid_FlightBook_Record;
+    US Pid_Lap;
+    US Pid_Wpt_Cat_Data;
+    US Pid_Run;
+    US Pid_Workout;
+    US Pid_Workout_Occurrence;
+    US Pid_Fitness_User_Profile;
+    US Pid_Workout_Limits;
+    US Pid_Course;
+    US Pid_Course_Lap;
+    US Pid_Course_Point;
+    US Pid_Course_Trk_Hdr;
+    US Pid_Course_Trk_Data;
+    US Pid_Course_Limits;
+    US Pid_Trk2_Hdr; /*Undocumented*/
+};
 
 
 
@@ -68,6 +84,15 @@ struct COMMANDDATA
     US Cmnd_Transfer_Lap;
     US Cmnd_Transfer_Wpt_Cats;
     US Cmnd_Transfer_Runs;
+    US Cmnd_Transfer_Workouts;
+    US Cmnd_Transfer_Workout_Occurrences;
+    US Cmnd_Transfer_Fitness_User_Profile;
+    US Cmnd_Transfer_Workout_Limits;
+    US Cmnd_Transfer_Courses;
+    US Cmnd_Transfer_Course_Laps;
+    US Cmnd_Transfer_Course_Points;
+    US Cmnd_Transfer_Course_Tracks;
+    US Cmnd_Transfer_Course_Limits;
 }
 ;
 
@@ -121,6 +146,11 @@ int32 gps_almanac_transfer;
 #define pA600 600
 int32 gps_date_time_transfer;
 
+/*
+ *  FlightBook Transfer Protocol
+ */
+#define pA650 650
+/*Not implemented */
 
 /*
  *  Position
@@ -141,10 +171,21 @@ int32 gps_pvt_transfer;
 #define pA906 906
 int32 gps_lap_transfer;
 
+/*
+ * Various fitness related
+ */
 #define pA1000 1000
 int32 gps_run_transfer;
-
-
+#define pA1002 1002
+int32 gps_workout_transfer;
+#define pA1004 1004
+int32 gps_user_profile_transfer;
+#define pA1005 1005
+int32 gps_workout_limits_transfer;
+#define pA1006 1006
+int32 gps_course_transfer;
+#define pA1009 1009
+int32 gps_course_limits_transfer;
 
 /*
  * Waypoint D Type
@@ -262,9 +303,37 @@ int32 gps_pvt_type;
  * Lap Data Type
  */
 #define pD906 906
+#define pD1001 1001
+#define pD1011 1011
+#define pD1015 1015
 
 int32 gps_lap_type;
 
+/*
+ * Various fitness related
+ */
+#define pD1000 1000
+#define pD1009 1009
+#define pD1010 1010
+int32 gps_run_type;
+#define pD1002 1002
+#define pD1008 1008
+int32 gps_workout_type;
+#define pD1003 1003
+int32 gps_workout_occurrence_type;
+#define pD1004 1004
+int32 gps_user_profile_type;
+#define pD1005 1005
+int32 gps_workout_limits_type;
+#define pD1006 1006
+int32 gps_course_type;
+#define pD1007 1007
+int32 gps_course_lap_type;
+#define pD1012 1012
+int32 gps_course_point_type;
+#define pD1013 1013
+int32 gps_course_limits_type;
+
 /*
  * Link protocol type
  */